package com.milling;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.msg.*;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ModbusCoilReader {
    private final Lock threadLock = new ReentrantLock();
    private ModbusMaster master;
//    private boolean[] Z0_X2; // 存储线圈状态

    public ModbusCoilReader(String host, int port) {
        // 初始化 Modbus TCP 主站
        ModbusFactory factory = new ModbusFactory();
        IpParameters params = new IpParameters();
        params.setHost(host);
        params.setPort(port);
        master = factory.createTcpMaster(params, true); // 启用长连接
    }

    public String readCoilsMitsubishi(int slaveId, int startAddress, int numberOfCoils) {
        threadLock.lock();
        try {
            master.init(); // 初始化连接

            // 构建读线圈请求（功能码 0x01）
            ReadCoilsRequest request = new ReadCoilsRequest(slaveId, startAddress, numberOfCoils);
            ReadCoilsResponse response = (ReadCoilsResponse) master.send(request);

            // 解析响应数据
            if (response.isException()) {
                System.err.println("Modbus 异常响应: " + response.getExceptionMessage());
                return "ERR";
            }

            // 获取线圈状态数组
            boolean[] coilStatuses = response.getBooleanData();
            for (int i = 0; i < numberOfCoils; i++) {
                System.out.println("Coil " + (startAddress + i) + ": " + coilStatuses[i]);
            }
//            Z0_X2 = new boolean[numberOfCoils];
//            System.arraycopy(coilStatuses, 0, Z0_X2, 0, numberOfCoils);

            return "OK";
        } catch (ModbusTransportException e) {
            System.err.println("Modbus 通信错误: " + e.getMessage());
            return "ERR";
        } catch (ModbusInitException e) {
            System.err.println("连接初始化失败: " + e.getMessage());
            return "ERR";
        } catch (Exception e) {
            System.err.println("未知错误: " + e.getMessage());
            return "ERR";
        } finally {
            threadLock.unlock();
        }
    }

    // 新增写入单个线圈方法
    public String writeCoilMitsubishi(int slaveId, int coilAddress, boolean value) {
        threadLock.lock();
        try {
            master.init(); // 初始化连接

            // 构建写线圈请求（功能码 0x05）
            WriteCoilRequest request = new WriteCoilRequest(slaveId, coilAddress, value);
            WriteCoilResponse response = (WriteCoilResponse) master.send(request);

            if (response.isException()) {
                System.err.println("Modbus 异常响应: " + response.getExceptionMessage());
                return "ERR";
            }

            // 验证写入结果（可选）
            System.out.println("写入成功 - 地址：" + coilAddress + " 值：" + value);
            return "OK";
        } catch (ModbusTransportException e) {
            System.err.println("Modbus 通信错误: " + e.getMessage());
            return "ERR";
        } catch (ModbusInitException e) {
            System.err.println("连接初始化失败: " + e.getMessage());
            return "ERR";
        } catch (Exception e) {
            System.err.println("未知错误: " + e.getMessage());
            return "ERR";
        } finally {
            threadLock.unlock();
        }
    }

    // 新增批量写入线圈方法（功能码0x0F）
    public String writeMultipleCoilsMitsubishi(int slaveId, int startAddress, boolean[] values) {
        threadLock.lock();
        try {
            master.init();

            // 创建批量写入请求（注意地址类型转换）
            WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startAddress, values);
            WriteCoilsResponse response = (WriteCoilsResponse) master.send(request);

            if (response.isException()) {
                System.err.println("Modbus批量写入异常: " + response.getExceptionMessage());
                return "ERR";
            }

            System.out.println("批量写入成功 - 起始地址：" + startAddress +
                    " 数量：" + values.length);
            return "OK";
        } catch (ModbusTransportException e) {
            System.err.println("Modbus通信异常: " + e.getMessage());
            return "ERR";
        } catch (ModbusInitException e) {
            System.err.println("连接初始化失败: " + e.getMessage());
            return "ERR";
        } catch (Exception e) {
            System.err.println("系统异常: " + e.getMessage());
            return "ERR";
        } finally {
            threadLock.unlock();
        }
    }

    public static void main(String[] args) {
        // 示例用法
        ModbusCoilReader reader = new ModbusCoilReader("192.168.237.178", 502);
        String result = reader.readCoilsMitsubishi(
                1,    // 从站 ID
                8193,  // 起始地址（例如 M100 对应地址 100）
                1    // 读取的线圈数量
        );
        System.out.println("读取结果: " + result);

        // 示例写入（地址应与PLC配置对应）
        String writeResult = reader.writeCoilMitsubishi(
                1,      // 从站ID
                8193,   // 要写入的线圈地址
                true    // 写入值
        );
        System.out.println("写入结果: " + writeResult);

        result = reader.readCoilsMitsubishi(
                1,    // 从站 ID
                8193,  // 起始地址（例如 M100 对应地址 100）
                1    // 读取的线圈数量
        );
        System.out.println("读取结果II: " + result);

        // 批量写入示例
        /*boolean[] batchValues = {true, false, true, true};
        String batchWriteResult = reader.writeMultipleCoilsMitsubishi(
                1,      // 从站ID
                8193,   // 起始地址
                batchValues
        );
        System.out.println("批量写入结果: " + batchWriteResult);

        // 验证写入结果（读取4个线圈）
        String verifyResult = reader.readCoilsMitsubishi(
                1,
                8193,
                4
        );
        System.out.println("验证读取结果: " + verifyResult);*/
    }
}
